import db.dao.BaseDao;
import entity.Article;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by zhongwei on 2017/6/10.
 */
public class ArticleCrawler {

    private static WebDriver driver;
    private static WebDriver detailDriver;
    private static String taskStr;
    private static BaseDao baseDao = new BaseDao();
    private static Set<String> links = new HashSet<>();
    private static int counter = 0;

    public ArticleCrawler() {
    }

    public static void main(String[] args) throws IOException {
        List<Article> articles = baseDao.find("from Article");
        for (Article article : articles) {
            links.add(article.getLink());
        }
        String os = System.getProperty("os.name");
        if (os.toLowerCase().contains("win")) {
            System.setProperty("webdriver.chrome.driver", "D:\\chromedriver.exe");
            URL url = ClassLoader.getSystemResource("gecko/geckodriver.exe");
            System.setProperty("webdriver.gecko.driver", url.getPath());
            driver = new ChromeDriver();
            detailDriver = new ChromeDriver();

        } else {
            driver = new ChromeDriver();
            detailDriver = new ChromeDriver();
        }
        List<String> tasks = FileUtils.readLines(new File("tasks"));
        for (String task : tasks) {
            counter = 0;
            taskStr = task;
            processOneTask(task);
        }
    }

    private static void processOneTask(String task) {
        driver.get("http://citeseer.ist.psu.edu/index");
        driver.manage().window().maximize();
        driver.findElement(By.xpath("//*[@id=\"search_docs\"]/form/div[1]/input[1]")).sendKeys(task);
        driver.findElement(By.xpath("//*[@id=\"search_docs\"]/form/div[1]/input[2]")).click();
        processOnePage();
        while (findAndClickNextPage()) {
            processOnePage();
        }
    }

    private static boolean findAndClickNextPage() {
        try {
            WebElement pager = driver.findElement(By.id("pager"));
            pager.click();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static void processOnePage() {
        List<WebElement> resultEles = driver.findElements(By.className("result"));
        for (WebElement resultEle : resultEles) {
            Article article = new Article();
            article.setDone(0);
            WebElement titleEle = tryFindEle(resultEle, By.tagName("h3"));
            String title = titleEle.getText();
            article.setTitle(title);
            String link = tryFindEle(titleEle, By.tagName("a")).getAttribute("href");
            if (links.contains(link))
                continue;
            article.setLink(link);
            String authors = "";
            try {
                authors = resultEle.findElement(By.className("authors")).getText();
            } catch (Exception e) {

            }
            article.setAuthors(authors);
            String pubVenue = "";
            String pubYearStr = "";
            int pubYear = 0;
            try {
                pubVenue = resultEle.findElement(By.className("pubvenue")).getText();
            } catch (Exception e) {
                //
            }
            try {
                pubYearStr = resultEle.findElement(By.className("pubyear")).getText().split(" ")[1];
                pubYear = Integer.parseInt(pubYearStr);
            } catch (Exception e) {

            }
            article.setPubVenue(pubVenue);
            article.setPubYear(pubYear);
            WebElement cite = tryFindEle(resultEle, By.className("citation"));
            String citationLink = cite.getAttribute("href");
            article.setCitationLink(citationLink);
            String citationNumStr = cite.getText();
            String[] arr = citationNumStr.split(" ");
            int citationCount = Integer.parseInt(arr[2]);
            article.setCitationCount(citationCount);
            String fromTask = taskStr;
            article.setFromTask(fromTask);
            openDetail(article, link);
            if (!links.contains(article.getLink())) {
                System.out.println(taskStr + " : " + counter++);
                baseDao.create(article);
                links.add(article.getLink());
            }
        }
    }

    private static void openDetail(Article article, String detailLink) {
        detailDriver.get(detailLink);
        String pdfLink = tryFindEles(tryFindEle(detailDriver, By.id("clinks")), By.tagName("a")).get(0).getAttribute("href");
        String summary = tryFindEle(tryFindEle(detailDriver, By.id("abstract")), By.tagName("p")).getText();
        String keywords = tryFindEle(tryFindEle(detailDriver, By.id("keywords")), By.tagName("p")).getText();
        article.setPdfLink(pdfLink);
        article.setKeyPhrases(keywords);
        article.setSummary(summary);
    }

    private static WebElement tryFindEle(By by) {
        try {
            return driver.findElement(by);
        } catch (Exception e) {
            return tryFindEle(by);
        }
    }

    private static WebElement tryFindEle(WebDriver driver, By by) {
        try {
            return driver.findElement(by);
        } catch (Exception e) {
            return tryFindEle(by);
        }
    }

    private static WebElement tryFindEle(WebElement element, By by) {
        try {
            return element.findElement(by);
        } catch (Exception e) {
            return tryFindEle(by);
        }
    }

    private static List<WebElement> tryFindEles(By by) {
        try {
            return driver.findElements(by);
        } catch (Exception e) {
            return tryFindEles(by);
        }
    }

    private static List<WebElement> tryFindEles(WebDriver driver, By by) {
        try {
            return driver.findElements(by);
        } catch (Exception e) {
            return tryFindEles(driver, by);
        }
    }

    private static List<WebElement> tryFindEles(WebElement element, By by) {
        try {
            return element.findElements(by);
        } catch (Exception e) {
            return tryFindEles(element, by);
        }
    }
}
